//
//  @ Project : Untitled
//  @ File Name : BundleContextImp.cpp
//  @ Date : 2009/8/31
//  @ Author : 
//
//

#include "FrameworkPublic.h"
#include "FrameworkEvent.h"
#include "FrameworkListener.h"
#include "FrameworkImp.h"
#include "ServiceReferenceImp.h"
#include "ServiceRegistrationImp.h"
#include "BundleImp.h"
#include "BundleContextImp.h"
#include "ServiceFactory.h"


USING_NAME_SPACE_OSGI

long BundleContextImp::m_NextAvailableServiceID = 1;
long BundleContextImp::m_NextAvailableBundleID = 1;
char* BundleContextImp::m_BundleLocationBase = 0;

int ParserManifestLine( const char* pLine, char* pProperty, char* pValue )
{
	if( pLine==0 || pProperty==0 || pValue==0 )
		return -1;

	int stage = 0; // 0, text head; 1, text body
	char* pDesChar = pProperty;
	char* pSrcChar = (char*)pLine;
	while( *pSrcChar ){
		if( *pSrcChar==':' ) {
			stage = 0;
			*pDesChar = 0;
			pDesChar = pValue;
			++pSrcChar;
		}
		if( *pSrcChar==' ' && stage==0 ) {
			++pSrcChar;
			continue;
		}
		*pDesChar = *pSrcChar;
		++pSrcChar;
		++pDesChar;
		stage = 1;
	}
	*pDesChar = 0;
	return 0;
}

Bundle* BundleContextImp::installBundle( const char* location ) 
{
	FrameworkImp* frame = static_cast<FrameworkImp*>(m_Framework);
	for( std::vector<BundleContext*>::iterator itor = frame->m_BundleRegistrys.begin(); 
		itor!=frame->m_BundleRegistrys.end(); ++itor ) {
			if( (*itor)->getBundle() && (*itor)->getBundle()->getBundleId()!=0 
				&& static_cast<BundleImp*>((*itor)->getBundle())->m_Location==location ) 
				return (*itor)->getBundle();
	}
	
	// parse location to get the bundle content
	std::string strBundleLocation = frame->m_BoundleLocationBase;
	strBundleLocation += location;
	strBundleLocation += ".mf";

	m_Bundle = 0;
	FILE* fp = fopen( strBundleLocation.c_str(), "r");
	if( fp ) {
		m_Bundle = new BundleImp(this, m_NextAvailableBundleID++);
		static_cast<BundleImp*>(m_Bundle)->m_Location = location;
		const int MAX_MF_LINE_COUNT = 512;
		char szLine[MAX_MF_LINE_COUNT] = {0};
		char szProperty[MAX_MF_LINE_COUNT] = {0};
		char szValue[MAX_MF_LINE_COUNT] = {0};
		while( !feof(fp) )
		{
			szLine[0] = 0;
			fgets( szLine, MAX_MF_LINE_COUNT, fp );

			if( strlen(szLine)>=MAX_MF_LINE_COUNT-1 ) {
				while( strlen(fgets( szLine, MAX_MF_LINE_COUNT, fp))>0 )
					;
				continue;
			}

			ParserManifestLine( szLine, szProperty, szValue );
			if( stricmp(szProperty,BUNDLE_NAME)==0 ) {
				static_cast<BundleImp*>(m_Bundle)->m_Name = szValue;
			} else if( _stricmp( szProperty, BUNDLE_SYMBOLICNAME)==0 ) {
				static_cast<BundleImp*>(m_Bundle)->m_SymbolicName = szValue;
			} else if( _stricmp( szProperty, BUNDLE_VERSION)==0 ) {
				static_cast<BundleImp*>(m_Bundle)->m_Version = Version(szValue);
			} else if( _stricmp( szProperty, BUNDLE_VENDOR)==0 ) {
				static_cast<BundleImp*>(m_Bundle)->m_Vendor = szValue;
			} else if( _stricmp( szProperty, BUNDLE_ACTIVATOR)==0 ) {
				static_cast<BundleImp*>(m_Bundle)->m_Activator = szValue;
			} else if( _stricmp( szProperty, BUNDLE_DESCRIPTION)==0 ) {
				static_cast<BundleImp*>(m_Bundle)->m_Description = szValue;
			} else if( _stricmp( szProperty, FRAGMENT_HOST)==0 ) {
				static_cast<BundleImp*>(m_Bundle)->m_Fragment = true;
			} else if( _stricmp( szProperty, BUNDLE_LOCALIZATION)==0 ) {
			} else if( _stricmp( szProperty, BUNDLE_COPYRIGHT)==0 ) {
			} else if( _stricmp( szProperty, BUNDLE_NATIVECODE_PROCESSOR)==0 ) {
			} else if( _stricmp( szProperty, BUNDLE_NATIVECODE_OSNAME)==0 ) {
			} else if( _stricmp( szProperty, BUNDLE_NATIVECODE_OSVERSION)==0 ) {
			} else if( _stricmp( szProperty, BUNDLE_NATIVECODE_LANGUAGE)==0 ) {
			} else if( _stricmp( szProperty, BUNDLE_REQUIREDEXECUTIONENVIRONMENT)==0 ) {
			}
		}
	}
	fclose(fp);
	frame->fireBundleEvent( BundleEvent::INSTALLED, m_Bundle);
	return m_Bundle;
}

Bundle* BundleContextImp::getBundle(long id )
{
	FrameworkImp* frame = static_cast<FrameworkImp*>(m_Framework);
	for( std::vector<BundleContext*>::iterator itor = frame->m_BundleRegistrys.begin(); 
		itor!=frame->m_BundleRegistrys.end(); ++itor ) {
			if( static_cast<BundleImp*>((*itor)->getBundle())->m_BundleID==id ) 
				return (*itor)->getBundle();
	}
	return 0;
}

void BundleContextImp::addServiceListener(ServiceListener* listener)
{
	std::list<ServiceListener*>::iterator itor = find( m_ServiceListeners.begin(), m_ServiceListeners.end(), listener );
	if( itor==m_ServiceListeners.end() ){
		m_ServiceListeners.push_back( listener );
	}
}

void BundleContextImp::removeServiceListener(ServiceListener* listener)
{
	std::remove( m_ServiceListeners.begin(), m_ServiceListeners.end(), listener );
}

void BundleContextImp::addBundleListener(BundleListener* listener)
{
	FrameworkImp* frame = static_cast<FrameworkImp*>(m_Framework);
	std::list<BundleListener*>::iterator itor = find( frame->m_BundleListers.begin(), frame->m_BundleListers.end(), listener );
	if( itor==frame->m_BundleListers.end() ){
		frame->m_BundleListers.push_back( listener );
	}
}

void BundleContextImp::removeBundleListener(BundleListener* listener)
{
	FrameworkImp* frame = static_cast<FrameworkImp*>(m_Framework);
	std::remove( frame->m_BundleListers.begin(), frame->m_BundleListers.end(), listener);
}

void BundleContextImp::addFrameworkListener(FrameworkListener* listener)
{
	FrameworkImp* frame = static_cast<FrameworkImp*>(m_Framework);
	std::list<FrameworkListener*>::iterator itor = find( frame->m_FrameworkListeners.begin(), frame->m_FrameworkListeners.end(), listener );
	if( itor==frame->m_FrameworkListeners.end() ){
		frame->m_FrameworkListeners.push_back( listener );
	}
}

void BundleContextImp::removeFrameworkListener(FrameworkListener* listener) 
{
   FrameworkImp* frame = static_cast<FrameworkImp*>(m_Framework);
   std::remove( frame->m_FrameworkListeners.begin(), frame->m_FrameworkListeners.end(), listener);
}

void BundleContextImp::registerService(char* clazz, Service* service)
{
	ServiceRegistrationImp* servieReg = new ServiceRegistrationImp( clazz, service, m_NextAvailableServiceID++ );
	ServiceReferenceImp* serviceRef = new ServiceReferenceImp( servieReg, m_Bundle );
	servieReg->BindServiceReference(serviceRef);
	m_ServiceRegistrys.push_back( servieReg );
}

ServiceReference* BundleContextImp::getServiceReference(char* clazz )
{
	for( std::vector<ServiceRegistration*>::iterator itor = m_ServiceRegistrys.begin();
		itor!=m_ServiceRegistrys.end(); ++itor ) {
			if( static_cast<ServiceRegistrationImp*>(*itor)->m_CalzzName==clazz ) 
				return (*itor)->getReference();
	}
	return 0;
}

Service* BundleContextImp::getService(ServiceReference* reference ) {
    ServiceReferenceImp* serviceRef = static_cast<ServiceReferenceImp*>(reference);
	ServiceRegistrationImp* serviceReg = static_cast<ServiceRegistrationImp*>(serviceRef->m_Registration);
	if( serviceReg->m_ServiceUseCount<=0 || serviceReg->m_Unregisted) 
		return 0;
	++serviceReg->m_ServiceUseCount;
	Service* service = 0;
	if( serviceReg->m_ServiceUseCount==1 && stricmp(serviceReg->m_Service->getServiceName(), "ServiceFactory" )==0 ) {
		service = static_cast<ServiceFactory*>(serviceReg->m_Service)->getService( m_Bundle, serviceReg );
	}
	return service;
}

bool BundleContextImp::ungetService(ServiceReference* reference)
{
	ServiceReferenceImp* service = static_cast<ServiceReferenceImp*>(reference);
	ServiceRegistrationImp* serviceReg = static_cast<ServiceRegistrationImp*>(service->m_Registration);
	if( serviceReg->m_ServiceUseCount<=0 || serviceReg->m_Unregisted) 
		return false;

	--serviceReg->m_ServiceUseCount;
	if( serviceReg->m_ServiceUseCount==0 && stricmp(serviceReg->m_Service->getServiceName(), "ServiceFactory" )==0 ) {
		static_cast<ServiceFactory*>(serviceReg->m_Service)->ungetService( m_Bundle, serviceReg, serviceReg->m_Service );
	}
	return true;
}
